package com.zwh.se.collection.comparable_comparator;

import java.util.Comparator;

/**
 * @author yexi
 * 除了可以通过实现 Comparable 来定义比较规则之外,还可以通过 java.util.Comparator 这个接口来达成自定义排序的需求。
 * 不过它与 Comparable 有很大的不同,要实现它的不是对象本身,而是 自定义比较器 。
 * 我们需要设计一个自定义的比较器类,然后再通过 Comparator<T> 的泛型将要比较的对象设计进去,然后比较器内部的比较规则我们再根据对象自定义。
 * 借此,我们可以设计多个不同的 自定义比较器 来比较同一个类的对象。
 * <p>
 * 由于此特性,我们一般称它为"外部比较器"。
 */
public class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }

    /**
     * 自定义排序比较规则
     * 排序规则：根据用户的名字长度顺序排序，如果名字长度相同则按照年龄顺序排序。
     */
    static public class NameLengthWithAgeComparator implements Comparator<User> {
        @Override
        public int compare(User o1, User o2) {
            int ret = o1.getName().length() - o2.getName().length();
            return ret > 0 ? 1 : ret < 0 ? -1 : Integer.compare(o1.getAge(), o2.getAge());
        }
    }

    /**
     * 排序规则：只根据用户的年龄顺序排序。
     */
    static public class AgeComparator implements Comparator<User> {
        @Override
        public int compare(User o1, User o2) {
            return Integer.compare(o1.getAge(), o2.getAge());
        }
    }

    public static void main(String[] args) {
        //比较两个学生：
        User s1 = new User("alili", 14);
        User s2 = new User("alili", 15);
        User s3 = new User("bnanas", 15);
        //获取到可以通过年龄来比较的比较器
        AgeComparator ageComparator = new AgeComparator();
        System.out.println(ageComparator.compare(s1, s2));
        System.out.println(ageComparator.compare(s2, s1));
        System.out.println(ageComparator.compare(s3, s2));
        //获取到名称长度与年龄比较器
        NameLengthWithAgeComparator nameLengthWithAgeComparator = new NameLengthWithAgeComparator();
        System.out.println(nameLengthWithAgeComparator.compare(s1, s2));
        System.out.println(nameLengthWithAgeComparator.compare(s2, s1));
        System.out.println(nameLengthWithAgeComparator.compare(s3, s2));

        //从上面的例子你就可以看出 Comparator 的好处是什么了,那就是可以通过多态来保证扩展性
        //  (由于写demo方便我才扔到一个文件里面的,实际你用的时候肯定是写到外面去的)
        //所以如果一个类的比较规则不是确定不变的,更建议使用 Comparator 来进行比较规则设计。
        //TIPS:没有完全取代是因为还有创建对象的内存资源消耗和泛型隐形强转等影响效率的问题哦。
        //      所有不要认为功能更强就可以完全取代,功能更强的东西往往需要先注意它的代价。

    }

}
